package com.katze.boot.plugins.security.filter;

import com.katze.boot.plugins.redis.service.CacheService;
import com.katze.boot.plugins.security.JwtTokenProvider;
import com.katze.boot.plugins.security.domain.UserDetail;
import com.katze.common.ResponseStatus;
import com.katze.common.http.HttpUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

public class JwtAuthenticationFilter extends OncePerRequestFilter implements IPathMatcher{
    @Lazy
    @Autowired
    private CacheService cacheService;

    private final String[] patterns;

    public JwtAuthenticationFilter() {
        patterns = new String[]{"/captcha.jpg", "/login", "/logout/**", "/regist", "/user/check/**"};
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        // 获取HTTP请求头中的认证令牌
        String token = request.getHeader(TOKEN_NAME);
        if (StringUtils.isBlank(token)) {
            chain.doFilter(request, response);
        } else {
            // 验证token有效性
            ResponseStatus status = JwtTokenProvider.verify(token, jwt->{
                String username = jwt.getClaim("username").asString();
                String tokenCache = cacheService.getToken(username);
                if (StringUtils.isBlank(tokenCache)){
                    // 认证失败，token失效或被强制下线
                    return ResponseStatus.TOKEN_INVALID;
                } else if (tokenCache.contains("@") && !HttpUtils.getRemoteAddress().equals(tokenCache.split("@")[1])){
                    // 认证失败,token绑定ip与当前发起请求的ip不符合
                    return ResponseStatus.TOKEN_NOT_MATCH_IP;
                } else {
                    // 认证成功，当前用户信息保存至本地线程ThreadLocal（默认ThreadLocalSecurityContextHolderStrategy.class）
                    UserDetail user = cacheService.loadUserByUsername(username, UserDetail.class);
                    if (user != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user, token, user.getAuthorities());
//                        authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); 暂时用不上先屏蔽
                        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                    }
                    return ResponseStatus.OK;
                }
            });
            // 认证失败抛出异常，ErrorReportValve
            if (status != ResponseStatus.OK){
                //方法1
//                request.setAttribute("jakarta.servlet.error.exception", new JwtAuthenticationException(status));
//                response.sendError(status.value());
                //方法2
                response.sendError(status.value(), status.note());
                return;
            }
            chain.doFilter(request, response);
        }
    }

    @Override
    public String[] getPatterns() {
        return patterns;
    }
}
